﻿using MingYuanYun.StructuredLog.Abstractions;
using Newtonsoft.Json;
using NLog;
using System;
using System.IO;
using System.Reflection;

namespace MingYuanYun.StructuredLog.NLog
{
    public class MyLogger : IMyLogger
    {
        private readonly MyLoggerOptions _options;

        public MyLogger(MyLoggerOptions options)
        {
            this._options = options;
        }

        //允许用户指定LoggerName
        private void Log(MyStructuredLog structuredLog, string loggerName)
        {
            ILogger logger = LogManager.GetLogger(loggerName);

            try
            {
                var log = JsonConvert.SerializeObject(structuredLog);

                if (!Enum.TryParse(structuredLog.Level, out MyLogLevel logLevel))
                {
                    logLevel = MyLogLevel.Unknown;
                }

                switch (logLevel)
                {
                    case MyLogLevel.Info:
                        logger.Info(log);
                        break;
                    case MyLogLevel.Error:
                        logger.Error(log);
                        break;
                    case MyLogLevel.Wraning:
                        logger.Warn(log);
                        break;
                    case MyLogLevel.Fatal:
                        logger.Fatal(log);
                        break;
                    case MyLogLevel.Unknown:
                        logger.Info(log);
                        break;
                    default:
                        logger.Info(log);
                        break;
                }

                //数据未格式化的日志文件
                logger.Debug(structuredLog.Description);

                if (structuredLog.Message.Message != "-")
                {
                    logger.Debug(structuredLog.Message.Message);
                    logger.Debug(structuredLog.Message.ErrorType);
                    logger.Debug(structuredLog.Message.CallStack);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex.ToString());
                logger.Debug(ex.ToString());
            }
        }

        private void Log(MyStructuredLog structuredLog)
        {
            Log(structuredLog, structuredLog.App);
        }

        public void InnerError(Exception ex)
        {
            ILogger logger = LogManager.GetLogger("StructuredNlog");

            logger.Debug(ex?.ToString());
        }

        public void Info(string description, string loggerName = "-")
        {
            Log(MyLogLevel.Info, description, "-", "-", "-", "-", -1, "-", "-", "-", loggerName);
        }

        public void Info(string description, int duration, string loggerName = "-")
        {
            Log(MyLogLevel.Info, description, "-", "-", "-", "-", duration, "-", "-", "-", loggerName);
        }
         
        public void Info(object descriptionObject, string loggerName = "-")
        {
            Log(MyLogLevel.Info, descriptionObject, "-", "-", "-", "-", -1, "-", "-", "-", loggerName);
        }

        public void Error(Exception ex, string loggerName = "-")
        {
            Log(MyLogLevel.Error, ex?.Message, ex?.Message, ex?.GetType().FullName, ex?.StackTrace, "-", -1, "-", "-", "-", loggerName, ex?.InnerException?.ToString());
        }

        public void Error(string description, Exception ex, string loggerName = "-")
        {
            Log(MyLogLevel.Error, description, ex?.Message, ex?.GetType().FullName, ex?.StackTrace, "-", -1, "-", "-", "-", loggerName, ex?.InnerException?.ToString());
        }

        public void Error(string description, Exception ex, int duration, string loggerName = "-")
        {
            Log(MyLogLevel.Error, description, ex?.Message, ex?.GetType().FullName, ex?.StackTrace, "-", duration, "-", "-", "-", loggerName, ex?.InnerException?.ToString());
        }

        public void Error(object descriptionObject, Exception ex, string loggerName = "-")
        {
            Log(MyLogLevel.Error, descriptionObject, ex?.Message, ex?.GetType().FullName, ex?.StackTrace, "-", -1, "-", "-", "-", loggerName, ex?.InnerException?.ToString());
        }

        private void Log(
            MyLogLevel logLevel,
            object descriptionObject,
            string errorMessage,
            string errorType,
            string callStack,
            string user,
            int duration,
            string functionOperator,
            string customizedValue,
            string context,
            string loggerName = "-",
            string innerException = "")
        {
            var structuredLog = new MyStructuredLog(_options);

            try
            {
                structuredLog.Level = logLevel.ToString();

                if (structuredLog.App == "-" || string.IsNullOrEmpty(structuredLog.App))
                {
                    structuredLog.App = Assembly.GetEntryAssembly()?.ToString(); //获得当前执行的程序集信息
                }

                structuredLog.AppPath = Directory.GetCurrentDirectory(); //获取实际执行路径名
                structuredLog.Description = JsonConvert.SerializeObject(descriptionObject ?? string.Empty);

                structuredLog.Message = new ErrorMessage { Message = errorMessage ?? "-", CallStack = callStack ?? "-", ErrorType = errorType ?? "-" };
                structuredLog.InnerException = innerException ?? "-";

                structuredLog.User = user;
                structuredLog.Duration = duration;
                structuredLog.Action = functionOperator;
                structuredLog.Context = context;
                structuredLog.CustomizedValve = customizedValue;
            }
            catch (Exception ex)
            {
                Error(ex);
            }

            if (loggerName == "-")
            {
                Log(structuredLog);
            }
            else
            {
                Log(structuredLog, loggerName);
            }
        }
    }
}
